/*
 * Copyright (c) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { IOException } from "./Error/error"

export class Protocol {
    static HTTP_1_0 = new Protocol("http/1.0")
    static HTTP_1_1 = new Protocol("http/1.1")
    static SPDY_3 = new Protocol("spdy/3.1")
    static HTTP_2 = new Protocol("h2")
    static H2_PRIOR_KNOWLEDGE = new Protocol("h2_prior_knowledge")
    static QUIC = new Protocol("quic")
    
    private readonly protocol: string

    constructor(protocol: string) {
        this.protocol = protocol;
    }

    /**
     * Returns the protocol string representation.
     * @returns The protocol string (e.g., "http/1.1", "h2")
     */
    public toString(): string {
        return this.protocol;
    }

    /**
     * Compares this protocol with another protocol for equality.
     * @param other - The protocol to compare with
     * @returns true if protocols are equal, false otherwise
     */
    public equals(other: Protocol | null): boolean {
        if (other === null || other === undefined) {
            return false;
        }
        return this.protocol === other.protocol;
    }

    /**
     * Gets a Protocol instance by its string representation.
     * Returns a known static protocol if available, otherwise creates a new instance.
     * @param protocol - The protocol string
     * @returns A Protocol instance
     */
    public static get(protocol: string): Protocol {
        switch (protocol.toLowerCase()) {
            case "http/1.0":
                return Protocol.HTTP_1_0;
            case "http/1.1":
                return Protocol.HTTP_1_1;
            case "spdy/3.1":
                return Protocol.SPDY_3;
            case "h2":
                return Protocol.HTTP_2;
            case "h2_prior_knowledge":
                return Protocol.H2_PRIOR_KNOWLEDGE;
            case "quic":
                return Protocol.QUIC;
            default:
                throw new IOException(`Unexpected protocol: ${protocol}`)
        }
    }
}